#include <stdio.h>
#include <string.h>

/*
 * This is probably one of the silliest programs I've made.
 * I wanted to get a good grasp of C function pointers.
 * I started by making an add function.  Then I made a pointer
 * to that add function, then I made an add3 function, which
 * has as one of it's parameters a pointer to add ().
 *
 * Then I made an add4 function, whose parameters include
 * a pointer to add3 () and a pointer to add ().
 *
 * It really starts getting complicated at that point.
 * That's why I made this program to see how easier it is to
 * make a program using typedefs.
 */

// a new type "fpAdd" is a function pointer expecting two integers
typedef int (*fpAdd) (int, int);

// a new type "fpAdd3" is a function pointer, expecting a function pointer
// of type fpAdd and three values.
typedef int (* fpAdd3) (fpAdd, int, int, int);

typedef int (* fpAdd4) (fpAdd3, fpAdd, int, int, int, int);

typedef int (* fpAdd5) (fpAdd4, fpAdd3, fpAdd, int, int, int, int, int);

int
add (int a, int b)
{
  return a + b;
}

/* a function that takes a function pointer,
   and 3 values */
int
add3 (fpAdd pAdd, int a, int b, int c)
{
  return (pAdd) (a, b) + c;
}

int
add4 (fpAdd3 pAdd3, fpAdd pAdd,
      int a, int b, int c, int d)
{
  return (pAdd3) (pAdd, a, b, c) + d;
}

int
add5 ( fpAdd4 pAdd4, fpAdd3 pAdd3, fpAdd pAdd,
       int a, int b, int c, int d, int e)  
{
  return (pAdd4) (pAdd3, pAdd, a, b, c, d) + e;
}

int
main ()
{
  // create a function pointer typedef 
  fpAdd pAdd = &add;
  int sum = (pAdd) (1, 1);
  printf ("sum is %d\n", sum);

  /* pAdd is a function pointer */
  int sum3 = add3 (pAdd, 1, 2, 3);

  printf ("sum3 is %d\n", sum3);

  //int (* pAdd3) (fpAdd pAdd, int a, int b, int c);
  fpAdd3 pAdd3 = &add3;
  sum3 = (pAdd3) (pAdd, 1, 2, 3);
  printf ("sum3 is still %d\n", sum3);

  int sum4 = add4 (pAdd3, pAdd, 1, 2, 3, 4);
  printf ("sum4 is %d\n", sum4);

  //int (*pAdd4) ( fpAdd3 pAdd3, fpAdd pAdd, int, int, int, int);
  fpAdd4 pAdd4 = &add4;
  sum4 = (pAdd4) (pAdd3, pAdd, 1, 2, 3, 4);
  printf ("sum4 is still %d\n", sum4);

  fpAdd5 pAdd5 = &add5;
  int sum5 = (pAdd5) (pAdd4, pAdd3, pAdd, 1, 2, 3, 4, 5);
  printf("sum5 is %d\n", sum5);

  
  return 0;
}
